﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace server
{
    internal class Server
    {
        public static async Task OnFail(HttpContext context)
        {
            await context.Response.WriteAsync("on 404:" + context.Request.GetDisplayUrl());
        }
        public static async Task OnAdmin_Clear(HttpContext context)
        {
            try
            {
                bool _succ = false;
                string _txt = "";
                bool waittag = false;
                dbtool.SafeClear((succ, txt) =>
                {
                    _succ = succ;
                    _txt = txt;
                    waittag = true;
                });
                while (!waittag)
                {
                    await Task.Delay(100);
                }
                var jobj = new JObject();
                jobj["succ"] = _succ;
                jobj["txt"] = _txt;
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
            catch (Exception err)
            {
                var jobj = new JObject();
                jobj["fail"] = "true";
                jobj["txt"] = err.Message;
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
        }
        public static async Task OnGetStatus(HttpContext context)
        {
            try
            {
                var s = dbtool.GetStatus();
                var jobj = new JObject();
                jobj["height"] = s.Height.ToString();
                jobj["inithash"] = HexTool.Hex2Str(s.Chain_InitHash);
                jobj["roothash"] = HexTool.Hex2Str(s.RootHash);
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
            catch (Exception err)
            {
                var jobj = new JObject();
                jobj["fail"] = "true";
                jobj["txt"] = err.Message;
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
        }

        static async Task<byte[]> ReadPostData(HttpContext context)
        {
            int seek = 0;
            byte[] data = null;
            var cc = context.Request.ContentType;
            //if(context.Response.ContentType =="")
            {
                data = new byte[(int)context.Request.ContentLength];
                while (seek < data.Length)
                {
                    var read = await context.Request.Body.ReadAsync(data, seek, data.Length - seek);
                    seek += read;
                }
            }
            return data;
        }
        //计算交易的Hash
        public static async Task OnTran_Calc(HttpContext context)
        {
            try
            {
                var s = dbtool.GetStatus();
                var roothash = HexTool.Str2Hex(context.Request.Query["roothash"]);
                var height = ulong.Parse(context.Request.Query["height"]);
                byte[] data = await ReadPostData(context);

                byte[] txhash = HexTool.CalcTranHash(height, roothash, data);
                var jobj = new JObject();
                jobj["txhash"] = HexTool.Hex2Str(txhash);
                jobj["roottest"] = HexTool.HexEqual(roothash, s.RootHash);
                jobj["heighttest"] = (height == s.Height + 1);
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
            catch (Exception err)
            {
                var jobj = new JObject();
                jobj["fail"] = "true";
                jobj["txt"] = err.Message;
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
        }
        public static async Task OnTran_Add(HttpContext context)
        {
            try
            {

                var s = dbtool.GetStatus();

                var roothash = HexTool.Str2Hex(context.Request.Query["roothash"]);
                var height = ulong.Parse(context.Request.Query["height"]);
                byte[] data = await ReadPostData(context);

                bool _succ = false;
                string _txt = "";
                bool waittag = false;
                dbtool.SafePutTran(height, roothash, data, (succ, txt) =>
                {
                    _succ = succ;
                    _txt = txt;
                    waittag = true;
                });
                while (!waittag)
                {
                    await Task.Delay(100);
                }

                byte[] txhash = HexTool.CalcTranHash(height, roothash, data);
                bool broottest = HexTool.HexEqual(roothash, s.RootHash);

                var txinfo = dbtool.GetTxInfo(txhash);
                var jobj = new JObject();
                jobj["succ"] = _succ;
                jobj["txexist"] = txinfo != null;
                jobj["txhash"] = HexTool.Hex2Str(txhash);
                if (txinfo != null)
                {
                    jobj["height"] = txinfo.Height.ToString();
                    jobj["datalen"] = txinfo.datalen.ToString();
                    jobj["roothash"] = HexTool.Hex2Str(txinfo.RootHash);//这个代表这个交易提交后的RootHash
                }



                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
            catch (Exception err)
            {
                var jobj = new JObject();
                jobj["fail"] = "true";
                jobj["txt"] = err.Message;
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
        }
        public static async Task OnTran_GetInfo(HttpContext context)
        {
            try
            {
                var txidstr = (context.Request.Query["txid"]).ToString();
                var txid = HexTool.Str2Hex(txidstr);
                var s = dbtool.GetTxInfo(txid);
                var jobj = new JObject();
                jobj["height"] = s.Height.ToString();
                jobj["datalen"] = s.datalen.ToString();
                jobj["txid"] = txidstr;
                jobj["roothash"] = HexTool.Hex2Str(s.RootHash);
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
            catch (Exception err)
            {
                var jobj = new JObject();
                jobj["fail"] = "true";
                jobj["txt"] = err.Message;
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
        }
        public static async Task OnTran_GetData(HttpContext context)
        {
            try
            {
                var txid = HexTool.Str2Hex(context.Request.Query["txid"]);
                var data = dbtool.GetTxData(txid);
                context.Response.StatusCode = 200;
                context.Response.ContentType = "application/octet-stream";
                await context.Response.Body.WriteAsync(data);
            }
            catch (Exception err)
            {
                var jobj = new JObject();
                jobj["fail"] = "true";
                jobj["txt"] = err.Message;
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
        }
        public static async Task OnTran_GetTxIDByHeight(HttpContext context)
        {
            try
            {
                var height = ulong.Parse(context.Request.Query["height"]);
                var txid = dbtool.GetTXIDByHeight(height);

                var jobj = new JObject();

                jobj["txid"] = HexTool.Hex2Str(txid);
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
            catch (Exception err)
            {
                var jobj = new JObject();
                jobj["fail"] = "true";
                jobj["txt"] = err.Message;
                context.Response.StatusCode = 200;
                context.Response.ContentType = "text/plain; charset=utf-8";
                await context.Response.WriteAsync(jobj.ToString());
            }
        }
    }
}
